package com.ly.mp.busicen.rule.flow.filter.plugin;

import static com.ly.mp.busicen.rule.XruleStrUtils.splitParam;
import static com.ly.mp.busicen.rule.XruleStrUtils.splitXKH;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.spel.SpelEvaluationException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.ly.mp.busicen.common.context.BusicenException;
import com.ly.mp.busicen.rule.flow.FlowSpelUtil;
import com.ly.mp.busicen.rule.flow.IActionContainer;
import com.ly.mp.busicen.rule.flow.action.Action;
import com.ly.mp.busicen.rule.flow.action.ActionResult;
import com.ly.mp.busicen.rule.flow.action.IAction;
import com.ly.mp.busicen.rule.flow.action.IActionResult.Signal;
import com.ly.mp.busicen.rule.flow.filter.FlowFilterBase;
import com.ly.mp.busicen.rule.flow.filter.FlowFilterException;
import com.ly.mp.busicen.rule.flow.filter.FlowInvocation;
import com.ly.mp.busicen.rule.flow.filter.FlowResult;
import com.ly.mp.busicen.rule.flow.filter.FlowResultImpl;


/**
 * 切换规则过滤器
 * @author ly-liuweisong
 *
 */
@Component
public class SwitchRuleFilter extends FlowFilterBase {
	
	@Autowired
	IActionContainer actionContainer;
	
	Logger log = LoggerFactory.getLogger(SwitchRuleFilter.class);

	@Override
	public FlowResult doInvoke(FlowInvocation invocation) {
		String paramStr = splitXKH(invocation.statement());
		if (!StringUtils.isEmpty(paramStr)) {
			Map<String, String> params = splitParam(paramStr);
			String rule = params.get("rule");
			String usedefualt = params.get("default");
			if (StringUtils.isEmpty(rule)) {
				log.info("流程【{}】节点【{}】SwitchRule规则切换参数为空，不进行规则切换",invocation.flowVolume().flow(),invocation.action().action());
			}else {
				try {
					try {
						log.info("流程【{}】节点【{}】SwitchRule解析表达式【{}】", invocation.flowVolume().flow(), invocation.action().action(),rule);
						String ruleCode = FlowSpelUtil.spelGetData(invocation.action(), rule,String.class);
						if (!StringUtils.isEmpty(ruleCode)) {
							log.info("流程【{}】节点【{}】SwitchRule获取规则编码为【{}】",invocation.flowVolume().flow(),invocation.action().action(),ruleCode);
							IAction newAction = actionContainer.action(ruleCode);
							if (newAction!=null) {
								if (newAction.operation().equals(invocation.action().operation())) {
									String contentOld = invocation.action().content();
									Action currentAction = (Action) invocation.action();
									currentAction.setContent(newAction.content());
									currentAction.setOperation(newAction.operation());
									try {
										return invocation.invoker().invoke(invocation);
									} finally {
										currentAction.setContent(contentOld);
									}
								}else {
									String errmsg = String.format("流程【%s】节点【%s}】SwitchRule获取规则对应操作类型与旧有不一致【%s】->【%s】",invocation.flowVolume().flow(),invocation.action().action(),invocation.action().operation(),newAction.operation());
									throw new FlowFilterException(errmsg);
								}								
							}
						}
						if ("true".equals(usedefualt)) {
							log.info("流程【{}】节点【{}】SwitchRule获取规则编码为空，不进行规则切换",invocation.flowVolume().flow(),invocation.action().action());
						}else {
							String errmsg = String.format("流程【%s】节点【%s】SwitchRule获取规则编码为空,获取规则不存在",invocation.flowVolume().flow(),invocation.action().action());
							throw new FlowFilterException(errmsg);
						}
						
						
					} catch (SpelEvaluationException e) {
						log.error("流程【{}】节点【{}】SwitchRule解析表达式【{}】失败", invocation.flowVolume().flow(),
								invocation.action().action(), paramStr, e);
						if (e.getCause()!=null&&e.getCause() instanceof InvocationTargetException) {
							InvocationTargetException ie = (InvocationTargetException) e.getCause();
							if (ie.getTargetException()!=null&&ie.getTargetException() instanceof BusicenException) {
								throw (BusicenException)ie.getTargetException();
							}
						}
						throw e;
					}
				} catch (Exception e) {
					ActionResult actionResult = ActionResult.create();
					actionResult.signal(Signal.EXCPT);
					actionResult.excpt(e);
					actionResult.action(invocation.action().action());
					actionResult.msg(invocation.action().msg());
					actionResult.data(null);
					FlowResultImpl flowResultImpl = new FlowResultImpl();
					flowResultImpl.setActionResult(actionResult);
					flowResultImpl.setException(e);
					return flowResultImpl;
				}
			}
		}else {
			log.info("流程【{}】节点【{}】SwitchRule规则切换参数为空，不进行规则切换",invocation.flowVolume().flow(),invocation.action().action());
		}
		return invocation.invoker().invoke(invocation);
	}

	@Override
	public String fileterName() {
		return "switchrule";
	}

}
